/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 * Modo de empleo:
 * Para subir un archico
 * 1- Crear el directorio en que se va a almacenar
 * 2- subir el o los archivos
 *
 * Para Crear un Directorio
 * 1- Simplemente pasar el path de todos los directorios necesarios hasta el que queramos.
 *
 * Para mover un archivo
 * 1- Se llama la funcion con la ruta del archivo en cuestion y el destino.
 */
package Control;

import java.io.*;
import java.util.Enumeration;
import java.util.zip.*;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;


/**
 *
 * @author leon
 */
public class ManejadorArchivos {

    private static String[] dirs;

    public static boolean crearDirectorios(String dirs) {
        boolean status = new File(dirs).mkdirs(); //crea todos los directorios
        return status; //si fueron creados retorna un true, caso contrario false
    }

    public static boolean borrar(String fileName) {
        File f = new File(fileName);
        // Make sure the file or directory exists and isn't write protected
        if (!f.exists()) {
            //throw new IllegalArgumentException("Borrar: no se encuentra archivo o directorio: " + fileName);
            System.out.println("El directorio " + fileName + " no se puede borrar porque no existe!");
            return true;
        }
        if (!f.canWrite()) {
            throw new IllegalArgumentException("Borrar: protegido contra escritura " + fileName);
        }
        // If it is a directory, make sure it is empty
        if (f.isDirectory()) {
            String[] files = f.list();
            if (files.length > 0) {
                throw new IllegalArgumentException("Borrar: directorio no vacio " + fileName);
            }
        }
        // Attempt to delete it
        boolean success = f.delete();
        if (!success) {
            throw new IllegalArgumentException("Borrar: el borrado fallo!");
        }
        return success;
    }

    public static boolean moverArchivo(String archivo, String destino) {
        File file = new File(archivo);
        // Destination directory
        File dir = new File(destino);
        // Move file to new directory
        boolean success = file.renameTo(new File(dir, file.getName()));
        if (!success) {
            throw new IllegalArgumentException("Move: mover fallo");
        }
        return true;
    }

    //moverArchivoRename mueve un archivo de archivo: ruta+archivo a destino: solamente ruta, y le pone el nombre nom
    //NO LA HE PROBADO A VER SI FUNCIONA.. JEJEJ QUE PENA
    public static boolean moverArchivoRename(String archivo, String destino, String nom) {
        File file = new File(archivo);
        // Destination directory
        File dir = new File(destino);
        // Move file to new directory
        boolean success = file.renameTo(new File(dir, file.getName()));
        File ren = new File(destino + nom);
        boolean rename = file.renameTo(new File(ren, ren.getName())); //renombra el archivo
        if (!success || !rename) {
            throw new IllegalArgumentException("Move: mover fallo");
        }
        return true;
    }
//renombra un archivo, asi: ruta la carpeta en la que esta el archivo, nombre el nombre del archivo y nuevo el nuevo nombre del archivo

    public static boolean rename(String ruta, String nombre, String nuevo) {
        File f1 = new File(ruta + nombre);
        File f2 = new File(ruta + nuevo);
        return f1.renameTo(f2);
    }

    public static boolean renameDir(String path, String nuevo, String antiguo) {
        try {
            
                copyFiles(path + antiguo , path + nuevo);
                if (delRec(path)) {
                    return true;
                } else {
                    return false;
                }
            
        } catch (IOException e) {
            return false;
        }
    }

    public static boolean copyFiles(String strPath, String dstPath) throws IOException {
        if (!strPath.equals(dstPath)) {
            File src = new File(strPath);
            File dest = new File(dstPath);

            if (src.isDirectory()) {

                dest.mkdirs();
                String list[] = src.list();

                for (int i = 0; i < list.length; i++) {
                    String dest1 = dest.getAbsolutePath() + "/" + list[i];
                    String src1 = src.getAbsolutePath() + "/" + list[i];
                    copyFiles(src1, dest1);
                }
            } else {
                InputStream in = new FileInputStream(src);
                OutputStream out = new FileOutputStream(dest);

                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = in.read(buffer)) >= 0) {

                    out.write(buffer, 0, bytesRead);
                }
                out.close();
                in.close();
            }
        }
        return true;
    }

    public static boolean guardarArchivo(HttpServletRequest request, String path) {
        try {
// Chequea que sea un request multipart (que se este enviando un file)


            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
            DiskFileItemFactory factory = new DiskFileItemFactory();
// maxima talla que sera guardada en memoria
            factory.setSizeThreshold(4096);
// si se excede de la anterior talla, se ira guardando temporalmente, en la sgte direccion
            factory.setRepository(new File(path));
            ServletFileUpload upload = new ServletFileUpload(factory);
//maxima talla permisible (si se excede salta al catch)
            upload.setSizeMax(167772160);//10000000
            List fileItems = upload.parseRequest(request);
//obtiene el file enviado
            Iterator i = fileItems.iterator();
            FileItem fi = (FileItem) i.next();
//graba el file enviado en el servidor local
//path y Nombre del archivo destino (en el server)
            String fileName = fi.getName(); //concatenamos el nombre de archivo con el tipo de contenido
            fi.write(new File(path, fileName));
            return true;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    public static boolean guardarArchivoConNombre(HttpServletRequest request, String path, String name) {
        try {
// Chequea que sea un request multipart (que se este enviando un file)
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
            DiskFileItemFactory factory = new DiskFileItemFactory();
// maxima talla que sera guardada en memoria
            factory.setSizeThreshold(4096);
// si se excede de la anterior talla, se ira guardando temporalmente, en la sgte direccion
            factory.setRepository(new File(path));
            ServletFileUpload upload = new ServletFileUpload(factory);
//maxima talla permisible (si se excede salta al catch)
            upload.setSizeMax(167772160);//10000000
            List fileItems = upload.parseRequest(request);
//obtiene el file enviado
            Iterator i = fileItems.iterator();
            FileItem fi = (FileItem) i.next();
//graba el file enviado en el servidor local
//path y Nombre del archivo destino (en el server)
            fi.write(new File(path, name));
            return true;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            return false;
        }
    }

    /*  Extraer (file, path)
     * Recibe dos parametros:
     * file: el archivo <Archivo.zip> a extrarer
     * path: La ruta de dicho archivo por ejemplo /home/leon/carpeta/
     * es importatne que la ruta incluya el ultimo "/"
     * Extrae un archivo zip en una carpeta con su mismo nombre pero sin la
     * extencion zip asi: archivo.zip => archivo/contenido
     * Respeta la jerarquia de directorios.
     */
    final static int BUFFER = 2048;

    public static boolean extraer(String file, String path) {
        try {
            String folder = file.substring(0, file.length() - 4) + "/";
            BufferedOutputStream dest = null;
            BufferedInputStream is = null;
            //System.out.println("File: " + file);
            //System.out.println("Path: " + path);
            ZipFile zipfile = new ZipFile(path + "/" + file);
            Enumeration e = zipfile.entries();
            //crea el directorio para descomprimir asi <directorio>.zip
            new File(path + "/" + folder).mkdirs();
            while (e.hasMoreElements()) {
                ZipEntry entry = (ZipEntry) e.nextElement();
                if (entry.isDirectory()) {
                    // Assume directories are stored parents first then children.
                    // This is not robust, just for demonstration purposes.
                    (new File(path + folder + entry.getName())).mkdirs();
                    //System.out.println("Creando Directorio: " + path + "/" + folder + entry.getName());
                    continue;
                }
                is = new BufferedInputStream(zipfile.getInputStream(entry));
                int count;
                byte data[] = new byte[BUFFER];
                FileOutputStream fos = new FileOutputStream(path + "/" + folder + entry.getName());
                //System.out.println("Escribiendo en: " + path + "/" + folder + entry.getName());
                dest = new BufferedOutputStream(fos, BUFFER);
                while ((count = is.read(data, 0, BUFFER)) != -1) {
                    dest.write(data, 0, count);
                }
                dest.flush();
                dest.close();
                is.close();
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /* doZip(archivo, salida)
     *  crea un archivo zip con el filename de entrada y produce el zipfilename como salida.
     */

    public static boolean doZip(String filename, String zipfilename) {
        try {
            byte[] buf = new byte[1024];
            FileInputStream fis = new FileInputStream(filename);
            fis.read(buf, 0, buf.length);
            CRC32 crc = new CRC32();
            ZipOutputStream s = new ZipOutputStream((OutputStream) new FileOutputStream(zipfilename));
            s.setLevel(6);
            ZipEntry entry = new ZipEntry(filename);
            entry.setSize((long) buf.length);
            crc.reset();
            crc.update(buf);
            entry.setCrc(crc.getValue());
            s.putNextEntry(entry);
            s.write(buf, 0, buf.length);
            s.finish();
            s.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /*  dirToZip (path, name, tarject)
     * Crea un archivo Zip con los archivos que existen dentro de path lo llama name.zip y lo guarda en tarject
     *
     * Ojo, solo los archivos dentro de path, si hay algun directorio LO OMITE
     */
    public static boolean dirToZip(String path, String name, String tarject) {
        try {
            BufferedInputStream origin = null;
            FileOutputStream dest = new FileOutputStream(tarject+name+".zip");
            ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
            //out.setMethod(ZipOutputStream.DEFLATED);
            byte data[] = new byte[BUFFER];
            // get a list of files from current directory
            File f = new File(path);
            String files[] = f.list();
            for (int i = 0; i < files.length; i++) {
                System.out.println("Adding: " + files[i]);
                FileInputStream fi = new FileInputStream(path+"/"+files[i]);
                origin = new BufferedInputStream(fi, BUFFER);
                ZipEntry entry = new ZipEntry(files[i]);
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0,BUFFER)) != -1) {
                    out.write(data, 0, count);
                }
                origin.close();
            }
            out.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            //return false;
        }
        return false;
    }


    /**
     * @return the dirs
     */
    public static String[] getDirs() {
        return dirs;
    }

    /**
     * @param aDirs the dirs to set
     */
    public static void setDirs(String[] aDirs) {
        dirs = aDirs;
    }

    public void copyInputStream(InputStream in, OutputStream out)
            throws IOException {
        byte[] buffer = new byte[1024];
        int len;
        while ((len = in.read(buffer)) >= 0) {
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();
    }
    //Lista los archivos de un path y retonra como String[]

    public static String[] listDir(String path) {
        File file = new File(path);
        return file.list();
    }
    //borra recursivamente los archivos y directorios de un path

    public static boolean delRec(String path) {
        File f = new File(path);
        if (!f.exists()) {
            return true;
        }
        String[] files = f.list();
        int i = 0, tope = files.length; //the lenght of the files inside the dir.

        for (i = 0; i < tope; i++) {
            File file = new File(path + "/" + files[i]);
            if (file.isDirectory()) {
                System.out.println("Borrando el directorio: " + path + "/" + files[i]);
                delRec(path + "/" + files[i]); //if is directory calls recursively
                if (!file.delete()) {//tengo q borrar el directorio ¬¬!, despues de vaciarlo
                    return false;
                }
            } else {
                System.out.println("Borrando el archivo: " + path + "/" + files[i]);
                if (!file.delete()) {
                    return false; //occurrio un error durante el borrado de archivos.
                }
            }
        }
        return true;
    }

    public static boolean fileExist(String path) {
        File file = new File(path);
        return file.exists();
    }
}
